<?php

namespace app\queue\stomp;

use app\queue\BaseConsumer;
use common\model\MessageTaskConfirmModel;
use common\model\TaskModel;
use common\service\StatusService;
use common\service\StepCategoryService;
use common\service\TemplateService;
use think\Exception;
use Webman\Stomp\RetryAbleConsumer;

/**
 * 异常信息存储队列
 */
class AbnormalStoreConsumer extends BaseConsumer // implements RetryAbleConsumer
{

    // 要消费的队列名
    public $queue = 'abnormal_info_store';

    // 连接名，对应 config/redis_queue.php 里的连接`
    public $connection = 'default';

    /**
     * 异常信息处理
     * @param $data
     * @throws \Throwable
     */
    public function doConsume($data)
    {
        // 解包data
        list($moduleCode, $abnormalType, $abnormalInfo, $operate) = $this->solveData($data);
        if (!in_array($moduleCode, ['entity', 'task', 'version'])) {
            return;
        }
        if (empty($data)) {
            return;
        }

        $affectedTaskList = $this->solveAffectedTask($moduleCode, $data);
        $affectedStepCategoryList = $this->solveStepCategory($moduleCode, $data, $affectedTaskList);
        $saveDataTemplate = [
            'link_id' => $data['id'],
            'link_module_code' => $moduleCode,
            'confirm' => 'default',
            'confirm_user_id' => 0,
            'source_type' => $abnormalType,
            'remark' => $abnormalInfo,
            'project_id' => $data['project_id'],
            'tenant_id' => \request()->getTenantId(),
            'created_by' => \request()->getUnionUserId(),
            'created' => time(),
        ];
        $saveData = [];
        // 每个环节存一条
        foreach ($affectedStepCategoryList as $stepCategory) {
            $saveData[] = array_replace($saveDataTemplate, ['link_step_category' => $stepCategory]);
        }
        model(MessageTaskConfirmModel::class)->addAll($saveData);
        return;
    }

    /**
     * 预处理, 解包data
     * @param $data
     * @return array
     */
    private function solveData(&$data)
    {
        // 循环处理配置项
        $operateList = split_array($data['operate'] ?? []);
        // 一个版本、任务、实体
        $moduleCode = $data['module_code'] ?? '';
        $abnormalType = $data['type'] ?? '';
        $abnormalInfo = $data['info'] ?? '';
        $data = $data['data'] ?? [];

        if ($moduleCode == 'version') {
            // 版本处理成任务
            $moduleCode = 'task';
            if (module_by_id($data['module_id'])['code'] == 'task') {
                $data = model(TaskModel::class)->find($data['link_id']);
            } else {
                $data = [];
            }
        }
        return [$moduleCode, $abnormalType, $abnormalInfo, $operateList];
    }

    /**
     * 查找下游工序任务
     * @param $moduleCode
     * @param $data
     * @return array|false|mixed|string
     */
    private function solveAffectedTask($moduleCode, $data)
    {
        $affectedTaskList = [];
        switch ($moduleCode) {
            case 'task':
                // 任务 查找下游环节任务
//            $affectedTaskList = TaskUpstreamService::getInstance()->getDownstreamTaskList($data['id']);
                break;
            case 'entity':
                // 实体 查找全部工序任务
                $affectedTaskList = model(TaskModel::class)
                    ->where([
                        'entity_id' => $data['id'],
                        'step_type' => 'step',
                        'json->>"$.task_status"' => ['IN', StatusService::getInstance()->byCodeMap(['closed', 'not_started'], true, 'id')],
                    ])
                    ->select();
                break;
        }
        return $affectedTaskList;
    }

    /**
     * 查找下游环节
     * @param $moduleCode
     * @param $originTask
     * @param $targetTaskList
     * @return array
     * @throws Exception
     */
    private function solveStepCategory($moduleCode, $originTask, $targetTaskList)
    {
        $stepCategoryList = [];
        // 环节打组
        $stepCategoryShowList = TemplateService::getInstance()->findStepCategoryShowList();
        $stepCategoryGroup = [];
        $stepCategoryGroupMap = [];
        foreach ($stepCategoryShowList as $stepCategoryItem) {
            $stepCategoryGroup[$stepCategoryItem['show_name']][] = $stepCategoryItem['id'];
        }
        foreach ($stepCategoryGroup as $showName => $stepCategoryIds) {
            sort($stepCategoryIds);
            foreach ($stepCategoryIds as $id) {
                $stepCategoryGroupMap[$id] = [
                    'id' => $showName,
                    'name' => $showName,
                    'children_ids' => $stepCategoryIds,
                ];
            }
        }

        $affectedStepCategoryList = [];
        switch ($moduleCode) {
            case "task":
                $upstreamRelation = StepCategoryService::getInstance()->upstreamRelation(['id' => $originTask['step_category_id']]);
                $upstreamRelation = array_column($upstreamRelation, null, 'id');
                $affectedStepCategoryList = $upstreamRelation[$originTask['step_category_id']]['downstream'] ?? [];
                break;
            case "entity":
                $affectedStepCategoryList = array_column($targetTaskList, 'step_category_id');
                break;
        }

        foreach ($affectedStepCategoryList as $downstream) {
            if (!isset($stepCategoryGroupMap[(int)$downstream])) {
                continue;
            }
            $currentStepCategoryList = implode(',', $stepCategoryGroupMap[(int)$downstream]['children_ids']);
            if (!in_array($currentStepCategoryList, $stepCategoryList)) {
                $stepCategoryList[] = $currentStepCategoryList;
            }
        }
        return $stepCategoryList;
    }
}
